#include "stdafx.h"
#include "ClientInformation.h"
#include <iostream>
using namespace std;


ConnectionInformation::ConnectionInformation()
	:m_csLock()
	,m_mapConnectionList()
{
	InitializeCriticalSection(&m_csLock);
}

void ConnectionInformation::SetFileType(SOCKET p_stClient,FileType p_stFileType)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stClient,it))
	{
		it->second.m_stFileType = p_stFileType;
	}
	else
	{
		Connection stClient;
		stClient.m_stFileType = p_stFileType;
		m_mapConnectionList.insert(make_pair(p_stClient,stClient));
	}
	LeaveCriticalSection(&m_csLock);
}


FileType ConnectionInformation::GetFileType(SOCKET p_stClient)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	FileType stFileType;
	if (true == IsConnectionExist(p_stClient,it))
	{
		stFileType = it->second.m_stFileType;
	}
	LeaveCriticalSection(&m_csLock);
	return stFileType;
}


void ConnectionInformation::SetRemoteIP(SOCKET p_stClient,string p_strIP)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stClient,it))
	{
		it->second.m_strRemoteIP = p_strIP;
	}
	else
	{
		Connection stClient;
		stClient.m_strRemoteIP = p_strIP;
		m_mapConnectionList.insert(make_pair(p_stClient,stClient));
	}
	LeaveCriticalSection(&m_csLock);
}

void ConnectionInformation::SetLocalIP(SOCKET p_stLocal,string p_strIP)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stLocal,it))
	{
		it->second.m_strLocalIP = p_strIP;
	}
	else
	{
		Connection stConnection;
		stConnection.m_strLocalIP = p_strIP;
		m_mapConnectionList.insert(make_pair(p_stLocal,stConnection));
	}
	LeaveCriticalSection(&m_csLock);
}

void ConnectionInformation::SetLocalPort(SOCKET p_stLocal,unsigned int p_uiPort)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stLocal,it))
	{
		it->second.m_uiLocalPort = p_uiPort;
	}
	else
	{
		Connection stConnection;
		stConnection.m_uiLocalPort = p_uiPort;
		m_mapConnectionList.insert(make_pair(p_stLocal,stConnection));
	}
	LeaveCriticalSection(&m_csLock);
}

string ConnectionInformation::GetRemoteIP(SOCKET p_stClient)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	string strIP;
	if (true == IsConnectionExist(p_stClient,it))
	{
		strIP = it->second.m_strRemoteIP;
	}	
	LeaveCriticalSection(&m_csLock);
	return strIP;
}

void ConnectionInformation::SetRemotePort(SOCKET p_stClient,unsigned int p_uiPort)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stClient,it))
	{
		it->second.m_uiRemotePort = p_uiPort;
	}
	else
	{
		Connection stClient;
		stClient.m_uiRemotePort = p_uiPort;
		m_mapConnectionList.insert(make_pair(p_stClient,stClient));
	}
	LeaveCriticalSection(&m_csLock);
}

void ConnectionInformation::SetConnectType(SOCKET p_stConnection,unsigned int p_uiConnectType)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stConnection,it))
	{
		it->second.m_uiConnectType = p_uiConnectType;
	}
	else
	{
		Connection stConnection;
		stConnection.m_uiConnectType = p_uiConnectType;
		m_mapConnectionList.insert(make_pair(p_stConnection,stConnection));
	}
	LeaveCriticalSection(&m_csLock);
}

void ConnectionInformation::SetConnection(SOCKET p_stConnectionSocket, Connection p_stConnection)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stConnectionSocket,it))
	{
		it->second.m_cLastSendTime = p_stConnection.m_cLastSendTime;
		it->second.m_dRecvBytes = p_stConnection.m_dRecvBytes;
		it->second.m_dSendBytes = p_stConnection.m_dSendBytes;
		it->second.m_stFileType = p_stConnection.m_stFileType;
		it->second.m_strLocalIP = p_stConnection.m_strLocalIP;
		it->second.m_strRemoteIP = p_stConnection.m_strRemoteIP;
		it->second.m_uiConnectType = p_stConnection.m_uiConnectType;
		it->second.m_uiLocalPort = p_stConnection.m_uiLocalPort;
		it->second.m_uiRemotePort = p_stConnection.m_uiRemotePort;
	}
	else
	{
		m_mapConnectionList.insert(make_pair(p_stConnectionSocket,p_stConnection));
	}
	LeaveCriticalSection(&m_csLock);
}

unsigned int ConnectionInformation::GetRemotePort(SOCKET p_stClient)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	unsigned int uiPort = 0;
	if (true == IsConnectionExist(p_stClient,it))
	{
		uiPort = it->second.m_uiRemotePort;
	}	
	LeaveCriticalSection(&m_csLock);
	return uiPort;
}

void ConnectionInformation::SetTransBytes(SOCKET p_stClient,double p_dSentBytes,double p_dRecvBytes)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stClient,it))
	{
		it->second.m_dSendBytes += p_dSentBytes;
		it->second.m_dRecvBytes += p_dRecvBytes;
	}
	else
	{
		Connection stClient;
		stClient.m_dSendBytes = p_dSentBytes;
		stClient.m_dRecvBytes = p_dRecvBytes;
		m_mapConnectionList.insert(make_pair(p_stClient,stClient));
	}
	LeaveCriticalSection(&m_csLock);
}

void ConnectionInformation::GetTransBytes(SOCKET p_stClient,double& p_dSentBytes,double& p_dRecvBytes)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stClient,it))
	{
		p_dSentBytes = it->second.m_dSendBytes;
		p_dRecvBytes = it->second.m_dRecvBytes;
	}
	else
	{
		p_dSentBytes = 0;
		p_dRecvBytes = 0;
	}
	LeaveCriticalSection(&m_csLock);
}

map<SOCKET,Connection> ConnectionInformation::GetConnectionList()
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection> mapConnection = m_mapConnectionList;
	LeaveCriticalSection(&m_csLock);
	return mapConnection;
}


bool ConnectionInformation::IsConnectionExist(SOCKET p_stClient, map<SOCKET,Connection>::iterator& p_it)
{
	p_it = m_mapConnectionList.find(p_stClient);
	if(p_it == m_mapConnectionList.end())
	{
		return false;
	}

	return true;
}

void ConnectionInformation::DeleteClient(SOCKET p_stClient)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it = m_mapConnectionList.find(p_stClient);
	if(it == m_mapConnectionList.end())
	{
		LOG(INFO) << "Cannot find socket:" << p_stClient << " from client list";
		LeaveCriticalSection(&m_csLock);
		return;
	}

	LOG(INFO) << "Client  " << it->second.m_strRemoteIP << ":" << it->second.m_uiRemotePort << " removed from client list";
	m_mapConnectionList.erase(it);
	LeaveCriticalSection(&m_csLock);
}

void ConnectionInformation::SetTime(SOCKET p_stClient,DateTime p_DateTime)
{
	EnterCriticalSection(&m_csLock);
	map<SOCKET,Connection>::iterator it;
	if (true == IsConnectionExist(p_stClient,it))
	{
		it->second.m_cLastSendTime = p_DateTime;
	}
	LeaveCriticalSection(&m_csLock);
}